﻿// CAddrRes.cpp: 实现文件
//

#include "pch.h"
#include "MY_PE_TOOL.h"
#include "CAddrRes.h"
#include "afxdialogex.h"


// CAddrRes 对话框

IMPLEMENT_DYNAMIC(CAddrRes, CDialogEx)

CAddrRes::CAddrRes(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_DIALOG2, pParent)
{

}

CAddrRes::~CAddrRes()
{
}

void CAddrRes::DoDataExchange(CDataExchange* pDX)
{
	CDialogEx::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_EDIT1, m_EditVA);
	DDX_Control(pDX, IDC_EDIT2, m_EditRVA);
	DDX_Control(pDX, IDC_EDIT3, m_EditFOA);
}


BEGIN_MESSAGE_MAP(CAddrRes, CDialogEx)
END_MESSAGE_MAP()


// CAddrRes 消息处理程序


void CAddrRes::SetFileDataAddr(char **pAddr)
{
	m_pFileData = pAddr;
}


void CAddrRes::SetFileDataSize(DWORD* pFileSize)
{
    m_pFileSize = pFileSize;
}

//根据偏移值和对齐值计算对齐后的大小
DWORD CAddrRes::CalcOffset(DWORD dwVal, DWORD dwAlign)
{
    if (dwVal % dwAlign == 0)
    {
        return dwVal;
    }
    else
    {
        return (dwVal / dwAlign + 1) * dwAlign;
    }

    return 0;
}


//用户通过VA算出RVA和FOA
void CAddrRes::VA_TO_RVA_AND_FOA()
{
	CString strVA;
	CString strRVA;
	CString strFOA;
	DWORD dwVA = 0;
	DWORD dwRVA = 0;
	DWORD dwFOA = 0;

    PIMAGE_DOS_HEADER pDosHead = (PIMAGE_DOS_HEADER)(*m_pFileData);
    PIMAGE_NT_HEADERS pNtHead = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
	PIMAGE_OPTIONAL_HEADER32 pOptionalHead = &pNtHead->OptionalHeader;
	PIMAGE_SECTION_HEADER pSectionHead = (PIMAGE_SECTION_HEADER)((DWORD)&pNtHead->OptionalHeader + pNtHead->FileHeader.SizeOfOptionalHeader);

	//获取用户输入的VA
	m_EditVA.GetWindowTextW(strVA);

	//将用户输入的值转换为数字
	dwVA = _tcstoul(strVA.GetBuffer(), 0, 16);

	//如果不在映射内,RVA 和 FA 给0
    if (dwVA <= pOptionalHead->ImageBase || dwVA >= pOptionalHead->SizeOfImage + pOptionalHead->ImageBase)
	{
        strVA.Format(_T("%08x"), dwVA);
		strRVA.Format(_T("%08x"), dwRVA);
		strFOA.Format(_T("%08x"), dwFOA);

        m_EditVA.SetWindowTextW(strVA);
		m_EditRVA.SetWindowTextW(strRVA);
		m_EditFOA.SetWindowTextW(strFOA);

		return;
	}

	//计算RVA
	dwRVA = dwVA - pOptionalHead->ImageBase;

	//如果RVA在PE头中，则RVA和FA一样
	if (dwRVA >= 0 && dwRVA < pOptionalHead->SizeOfHeaders)
	{
		dwFOA = dwRVA;

        strVA.Format(_T("%08x"), dwVA);
        strRVA.Format(_T("%08x"), dwRVA);
        strFOA.Format(_T("%08x"), dwFOA);

        m_EditVA.SetWindowTextW(strVA);
        m_EditRVA.SetWindowTextW(strRVA);
        m_EditFOA.SetWindowTextW(strFOA);

		return;
	}

	//计算PE头在内存对齐后的大小
	DWORD dwMemRVA = CalcOffset(pOptionalHead->SizeOfHeaders, pOptionalHead->SectionAlignment);

	//如果在PE头中，但是在内存中存在，在文件中不存在，FA给0
    if (dwRVA > 0 && dwRVA < dwMemRVA)
    {
        strVA.Format(_T("%08x"), dwVA);
        strRVA.Format(_T("%08x"), dwRVA);
        strFOA.Format(_T("%08x"), dwFOA);

        m_EditVA.SetWindowTextW(strVA);
        m_EditRVA.SetWindowTextW(strRVA);
        m_EditFOA.SetWindowTextW(strFOA);

		return;
    }

	//在节表中
	for (int i = 0; i < pNtHead->FileHeader.NumberOfSections; i++)
	{
        //计算出每个节区在内存中占用多大内存空间
        DWORD dwTemp = 0;
        if (pSectionHead[i].SizeOfRawData > pSectionHead[i].Misc.VirtualSize)
        {
            dwTemp = CalcOffset(pSectionHead[i].SizeOfRawData, pOptionalHead->SectionAlignment);
        }
        else
        {
            dwTemp = CalcOffset(pSectionHead[i].Misc.VirtualSize, pOptionalHead->SectionAlignment);
        }


        //判断该RVA是否在这个节区中
        if (dwRVA >= pSectionHead[i].VirtualAddress && dwRVA < pSectionHead[i].VirtualAddress + dwTemp)
        {
            //如果该RVA在文件中有映射，则显示
            if (dwRVA <= pSectionHead[i].SizeOfRawData + pSectionHead[i].VirtualAddress)
            {
                DWORD dwDiffVal = dwRVA - pSectionHead[i].VirtualAddress;
                dwFOA = pSectionHead[i].PointerToRawData + dwDiffVal;

                strVA.Format(_T("%08x"), dwVA);
                strRVA.Format(_T("%08x"), dwRVA);
                strFOA.Format(_T("%08x"), dwFOA);

                m_EditVA.SetWindowTextW(strVA);
                m_EditRVA.SetWindowTextW(strRVA);
                m_EditFOA.SetWindowTextW(strFOA);

                return;
            }
            //该RVA在文件中没有映射
            else
            {
                strVA.Format(_T("%08x"), dwVA);
                strRVA.Format(_T("%08x"), dwRVA);
                strFOA.Format(_T("%08x"), dwFOA);

                m_EditVA.SetWindowTextW(strVA);
                m_EditRVA.SetWindowTextW(strRVA);
                m_EditFOA.SetWindowTextW(strFOA);

                return;
            }
        }
	}
}


//用户通过RVA算出VA和FOA
void CAddrRes::RVA_TO_VA_AND_FOA()
{
    CString strVA;
    CString strRVA;
    CString strFOA;
    DWORD dwVA = 0;
    DWORD dwRVA = 0;
    DWORD dwFOA = 0;

    PIMAGE_DOS_HEADER pDosHead = (PIMAGE_DOS_HEADER)(*m_pFileData);
    PIMAGE_NT_HEADERS pNtHead = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
    PIMAGE_OPTIONAL_HEADER32 pOptionalHead = &pNtHead->OptionalHeader;
    PIMAGE_SECTION_HEADER pSectionHead = (PIMAGE_SECTION_HEADER)((DWORD)&pNtHead->OptionalHeader + pNtHead->FileHeader.SizeOfOptionalHeader);

    //获取用户输入的RVA
    m_EditRVA.GetWindowTextW(strRVA);

    //将用户输入的值转换为数字
    dwRVA = _tcstoul(strRVA.GetBuffer(), 0, 16);

    //计算VA
    dwVA = dwRVA + pOptionalHead->ImageBase;

    //如果不在映射内, FA 给0
    if (dwVA <= pOptionalHead->ImageBase || dwVA >= pOptionalHead->SizeOfImage + pOptionalHead->ImageBase)
    {
        strVA.Format(_T("%08x"), dwVA);
        strRVA.Format(_T("%08x"), dwRVA);
        strFOA.Format(_T("%08x"), dwFOA);

        m_EditVA.SetWindowTextW(strVA);
        m_EditRVA.SetWindowTextW(strRVA);
        m_EditFOA.SetWindowTextW(strFOA);

        return;
    }

    //如果RVA在PE头中，则RVA和FA一样
    if (dwRVA >= 0 && dwRVA < pOptionalHead->SizeOfHeaders)
    {
        dwFOA = dwRVA;

        strVA.Format(_T("%08x"), dwVA);
        strRVA.Format(_T("%08x"), dwRVA);
        strFOA.Format(_T("%08x"), dwFOA);

        m_EditVA.SetWindowTextW(strVA);
        m_EditRVA.SetWindowTextW(strRVA);
        m_EditFOA.SetWindowTextW(strFOA);

        return;
    }

    //计算PE头在内存对齐后的大小
    DWORD dwMemRVA = CalcOffset(pOptionalHead->SizeOfHeaders, pOptionalHead->SectionAlignment);

    //如果在PE头中，但是在内存中存在，在文件中不存在，FA给0
    if (dwRVA > 0 && dwRVA < dwMemRVA)
    {
        strVA.Format(_T("%08x"), dwVA);
        strRVA.Format(_T("%08x"), dwRVA);
        strFOA.Format(_T("%08x"), dwFOA);

        m_EditVA.SetWindowTextW(strVA);
        m_EditRVA.SetWindowTextW(strRVA);
        m_EditFOA.SetWindowTextW(strFOA);

        return;
    }

    //在节表中
    for (int i = 0; i < pNtHead->FileHeader.NumberOfSections; i++)
    {
        //计算出每个节区在内存中占用多大内存空间
        DWORD dwTemp = 0;
        if (pSectionHead[i].SizeOfRawData > pSectionHead[i].Misc.VirtualSize)
        {
            dwTemp = CalcOffset(pSectionHead[i].SizeOfRawData, pOptionalHead->SectionAlignment);
        }
        else
        {
            dwTemp = CalcOffset(pSectionHead[i].Misc.VirtualSize, pOptionalHead->SectionAlignment);
        }


        //判断该RVA是否在这个节区中
        if (dwRVA >= pSectionHead[i].VirtualAddress && dwRVA < pSectionHead[i].VirtualAddress + dwTemp)
        {
            //如果该RVA在文件中有映射，则显示
            if (dwRVA <= pSectionHead[i].SizeOfRawData + pSectionHead[i].VirtualAddress)
            {
                DWORD dwDiffVal = dwRVA - pSectionHead[i].VirtualAddress;
                dwFOA = pSectionHead[i].PointerToRawData + dwDiffVal;

                strVA.Format(_T("%08x"), dwVA);
                strRVA.Format(_T("%08x"), dwRVA);
                strFOA.Format(_T("%08x"), dwFOA);

                m_EditVA.SetWindowTextW(strVA);
                m_EditRVA.SetWindowTextW(strRVA);
                m_EditFOA.SetWindowTextW(strFOA);

                return;
            }
            //该RVA在文件中没有映射
            else
            {
                strVA.Format(_T("%08x"), dwVA);
                strRVA.Format(_T("%08x"), dwRVA);
                strFOA.Format(_T("%08x"), dwFOA);

                m_EditVA.SetWindowTextW(strVA);
                m_EditRVA.SetWindowTextW(strRVA);
                m_EditFOA.SetWindowTextW(strFOA);

                return;
            }
        }
    }
}


//用户通过FOA算出VA和RVA
void CAddrRes::FOA_TO_VA_AND_RVA()
{
    CString strVA;
    CString strRVA;
    CString strFOA;
    DWORD dwVA = 0;
    DWORD dwRVA = 0;
    DWORD dwFOA = 0;

    PIMAGE_DOS_HEADER pDosHead = (PIMAGE_DOS_HEADER)(*m_pFileData);
    PIMAGE_NT_HEADERS pNtHead = (PIMAGE_NT_HEADERS)((DWORD)pDosHead + pDosHead->e_lfanew);
    PIMAGE_OPTIONAL_HEADER32 pOptionalHead = &pNtHead->OptionalHeader;
    PIMAGE_SECTION_HEADER pSectionHead = (PIMAGE_SECTION_HEADER)((DWORD)&pNtHead->OptionalHeader + pNtHead->FileHeader.SizeOfOptionalHeader);

    //获取用户输入的FA
    m_EditFOA.GetWindowTextW(strFOA);

    //将用户输入的值转换为数字
    dwFOA = _tcstoul(strFOA.GetBuffer(), 0, 16);

    //判断是否在文件大小内
    if (dwFOA < 0 || dwFOA >= *m_pFileSize)
    {
        //如果不在文件大小内，则VA 和 RVA 给 0
        strVA.Format(_T("%08x"), dwVA);
        strRVA.Format(_T("%08x"), dwRVA);
        strFOA.Format(_T("%08x"), dwFOA);

        m_EditVA.SetWindowTextW(strVA);
        m_EditRVA.SetWindowTextW(strRVA);
        m_EditFOA.SetWindowTextW(strFOA);

        return;
    }

    //判断是否在PE头文件中
    if (dwFOA >= 0 && dwFOA < pOptionalHead->SizeOfHeaders)
    {
        //如果在PE头中，则RVA和FA一样
        dwRVA = dwFOA;
        dwVA = dwRVA + pOptionalHead->ImageBase;

        strVA.Format(_T("%08x"), dwVA);
        strRVA.Format(_T("%08x"), dwRVA);
        strFOA.Format(_T("%08x"), dwFOA);

        m_EditVA.SetWindowTextW(strVA);
        m_EditRVA.SetWindowTextW(strRVA);
        m_EditFOA.SetWindowTextW(strFOA);
    }


    //FA在节表中
    for (int i = 0; i < pNtHead->FileHeader.NumberOfSections; i++)
    {
        //判断该FA是否在这个节区中
        if (dwFOA >= pSectionHead[i].PointerToRawData && dwFOA < pSectionHead[i].PointerToRawData + pSectionHead[i].SizeOfRawData)
        {
            //如果在这个节区,计算RVA
            dwRVA = dwFOA - pSectionHead[i].PointerToRawData + pSectionHead[i].VirtualAddress;

            //计算VA
            dwVA = dwRVA + pOptionalHead->ImageBase;

            strVA.Format(_T("%08x"), dwVA);
            strRVA.Format(_T("%08x"), dwRVA);
            strFOA.Format(_T("%08x"), dwFOA);

            m_EditVA.SetWindowTextW(strVA);
            m_EditRVA.SetWindowTextW(strRVA);
            m_EditFOA.SetWindowTextW(strFOA);

            return;
        }
    }
}


BOOL CAddrRes::PreTranslateMessage(MSG* pMsg)
{
	if (pMsg->message == WM_KEYDOWN && VK_RETURN == pMsg->wParam)
	{
		//用户输出VA
		if (pMsg->hwnd == m_EditVA.GetSafeHwnd())
		{
			VA_TO_RVA_AND_FOA();
			return TRUE;
		}
		//用户输出RVA
		else if (pMsg->hwnd == m_EditRVA.GetSafeHwnd())
        {
			RVA_TO_VA_AND_FOA();
            return TRUE;
		}
		//用户输出FOA
		else if (pMsg->hwnd == m_EditFOA.GetSafeHwnd())
		{
			FOA_TO_VA_AND_RVA();
			return TRUE;
		}
		else
		{
			return TRUE;
		}
	}

    return CDialogEx::PreTranslateMessage(pMsg);
}
